package com.jeff.work;

import java.util.Arrays;
import java.util.Comparator;


public class JobScheduling {


    /**
     * 模拟短作业优先（SJF）进程调度算法。
     * 对输入的进程数组按照作业长度进行排序
     * 最后，打印出所有进程的调度信息。
     *
     * @param arr 进程控制块数组，每个进程控制块包含进程名称、提交时间、运行时间等信息。
     */
    public static void SJF(PCB[] arr) {
        // 对输入的进程数组按照作业长度进行排序，以便优先调度作业时间短的进程
        Arrays.sort(arr, Comparator.comparingDouble(job -> job.getJobLength()));

        int currentTime = 0;
        // 遍历进程数组，计算每个进程的结束时间，并为下一个进程设置开始时间
        for (PCB pcb : arr) {
            // 计算每一个进程的开始时间 当前时间+提交时间
            pcb.setStartTime(currentTime+pcb.getSubmitTime());
            // 计算当前进程的结束时间
            pcb.setFinishTime(pcb.getStartTime() + pcb.getBurstTime());
            // 将currentTime更新为当前进程的结束时间
            currentTime = pcb.getFinishTime();
        }

        // 打印SJF进程调度的结果
        System.out.println("模拟短作业优先（SJF）进程调度:");
        System.out.println("进程名称 | 提交时间 | 运行时间 | 开始时间 | 结束时间");

        Arrays.stream(arr).forEach(pcb -> {
            System.out.println(pcb.getName() + " | " + pcb.getSubmitTime() + " | " + pcb.getBurstTime() + " | " + pcb.getStartTime() + " | " + pcb.getFinishTime());
        });
    }


    /**
     * 模拟先来先服务（FCFS）进程调度算法。
     * 该方法接收一个进程控制块（PCB）数组，数组中的每个元素代表一个进程。
     * 方法首先根据进程的到达时间对进程进行排序，然后计算每个进程的开始时间和结束时间。
     * 最后，打印出每个进程的调度信息，包括进程名称、提交时间、运行时间、开始时间和结束时间。
     *
     * @param arr 进程控制块（PCB）数组，每个PCB包含进程的名称、提交时间、运行时间和相关信息。
     */
    public static void FCFS(PCB arr[]) {
        // 根据进程的提交时间对数组进行排序，以模拟FCFS调度算法
        Arrays.sort(arr, Comparator.comparingDouble(a -> a.getSubmitTime()));

        int currentTime = 0;
        // 遍历进程数组，计算每个进程的结束时间，并为下一个进程设置开始时间
        for (PCB pcb : arr) {
            // 计算每一个进程的开始时间 当前时间+到达时间
            pcb.setStartTime(currentTime+pcb.getSubmitTime());
            // 计算当前进程的结束时间
            pcb.setFinishTime(pcb.getStartTime() + pcb.getBurstTime());
            // 将currentTime更新为当前进程的结束时间
            currentTime = pcb.getFinishTime();
        }

        // 打印FCFS调度结果
        System.out.println("模拟先来先服务（FCFS）进程调度:");
        System.out.println("进程名称 | 提交时间 | 运行时间 | 开始时间 | 结束时间");
        Arrays.stream(arr).forEach(pcb -> {
            System.out.println(pcb.getName() + " | " + pcb.getSubmitTime() + " | " + pcb.getBurstTime() + " | " + pcb.getStartTime() + " | " + pcb.getFinishTime());
        });
    }


    /**
     * 模拟最高响应比优先（HRRN）进程调度算法。
     * 根据进程的提交时间、运行时间和优先级计算响应比，并据此进行调度。
     *
     * @param arr PCB数组，包含所有进程的控制块。
     */
    public static void HRRN(PCB[] arr) {

        // 计算每个进程的等待时间和服务时间
        for (PCB pcb : arr) {
            pcb.startTime = Math.max(pcb.getSubmitTime(), pcb.getFinishTime()); // 计算开始时间
            pcb.finishTime = pcb.getStartTime() + pcb.getBurstTime(); // 计算结束时间
        }

        // 对进程数组按照响应比进行排序
        Arrays.sort(arr, Comparator.comparingDouble(PCB::getResponseRatio));

        // 输出调度结果
        System.out.println("模拟最高响应比优先（HRRN）进程调度:");
        System.out.println("进程名称 | 提交时间 | 运行时间 | 开始时间 | 结束时间");
        Arrays.stream(arr).forEach(pcb -> {
            System.out.println(pcb.getName() + " | " + pcb.getSubmitTime() + " | " + pcb.getBurstTime() + " | " + pcb.getStartTime() + " | " + pcb.getFinishTime());
        });
    }






    public static void main(String[] args) {
        PCB[] arr = {
                new PCB("job1", 1, 5, 2,0,5),
                new PCB("job2", 4, 3, 4,0,3),
                new PCB("job3", 2, 4, 3,0,4),
                new PCB("job4", 3, 1, 1,0,1),
                new PCB("job5", 5, 2, 5,0,2)
        };

        SJF(arr);
        FCFS(arr);
        HRRN(arr);
    }
}